package com.eight.customer;

import com.eight.feign.CarOrderFeign;
import com.eight.feign.UserChargeFeign;
import com.eight.pojo.TbOrder;
import com.eight.pojo.UserCharge;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;

/**
 * @Description: 用户充值的消费者
 * @Author: Van.Planifolia
 * @CreateTime: 2023-03-08  20:04
 * @Version: 1.0
 */
@Component
@Slf4j
public class OrderCustomer {
    @Autowired
    private StringRedisTemplate redis;
    @Autowired
    private UserChargeFeign userChargeFeign;
    @Autowired
    private CarOrderFeign carOrderFeign;


    /**
     * 消费方法，消费充值队列中的一条记录
     *
     * @param message 消息
     * @param channel 批准消息
     */
    @RabbitListener(queues = {"chargeOrderSurviveQueue"})
    public void chargeOrderCustomer(Message message, Channel channel) throws IOException {
        String correlationId = message.getMessageProperties().getCorrelationId();
        try {
            //处理订单支付成功消息
            // 如果雷迪斯中有这个消息id就证明该消息确实付款了可用消费消息
            if (StringUtils.hasText(redis.opsForValue().get(correlationId))) {
                System.out.println("消息,id:" + correlationId + "内容:" + new String(message.getBody()) + "确实消费了");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                // 修改状态为已经支付
                userChargeFeign.upStatus(correlationId, 1);
                redis.delete(correlationId);
            } else {
                // 否则就抛出异常重新入队
                throw new RuntimeException();
            }
        } catch (Exception e) {
            //消息重新入队
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), true, true);
        }
    }

    /**
     * 消费方法，消费租车队列中的一条记录
     *
     * @param message 消息
     * @param channel 批准消息
     */
    @RabbitListener(queues = {"carOrderSurviveQueue"})
    public void carOrderCustomer(Message message, Channel channel) throws IOException {
        String correlationId = message.getMessageProperties().getCorrelationId();
        try {
            //处理订单支付成功消息
            // 如果雷迪斯中有这个消息id就证明该消息确实付款了可用消费消息
            if (StringUtils.hasText(redis.opsForValue().get(correlationId))) {
                log.info("消息: id-> " + correlationId + "内容-> " + new String(message.getBody()) + "确实被正常消费了!");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                redis.delete(correlationId);
                carOrderFeign.changeStateByUuid(1, correlationId);
            } else {
                // 否则就抛出异常重新入队
                throw new RuntimeException();
            }
        } catch (Exception e) {
            //消息重新入队
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), true, true);
        }
    }

    /**
     * 充值死信队列的消费者也就是超时自动清除
     *
     * @param message 消息对象
     * @param channel 确认机制
     */
    @RabbitListener(queues = {"chargeOrderDeadQueue"})
    public void customerDeadChargeOrder(Message message, Channel channel) {
        // 取出消息的id
        String correlationId = message.getMessageProperties().getCorrelationId();
        // 处理清除订单业务
        UserCharge userCharge = userChargeFeign.selectChargeOrder(correlationId);
        // 如果订单的状态还是为0.那么我们就要将他标记为已经超时
        // 否则就不做任何操作
        try {
            // 安全判断
            if (userCharge == null) {
                log.warn("警告：消息 [id->" + correlationId + "内容->" + new String(message.getBody()) + "可能在数据库中不存在，所以这里直接进行消费！");
            } else if (0 == userCharge.getState()) {
                userChargeFeign.upStatus(correlationId, 4);
                log.info("消息: id->" + correlationId + "内容->" + new String(message.getBody()) + "确实被超时消费了");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 租车死信队列的消费者也就是超时自动清除
     *
     * @param message 消息对象
     * @param channel 确认机制
     */
    @RabbitListener(queues = {"carOrderDeadQueue"})
    public void customerDeadCarOrder(Message message, Channel channel) {
        // 取出消息的id
        String correlationId = message.getMessageProperties().getCorrelationId();
        //处理订单支付成功消息
        TbOrder tbOrder = carOrderFeign.getOrderByUuid(correlationId);
        // 确认消息,进行短路判断若查询的结果直接为null就直接确认
        try {
            if (tbOrder == null) {
                log.warn("警告：消息 [id->" + correlationId + "内容->" + new String(message.getBody()) + "可能在数据库中不存在，所以这里直接进行消费！");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
                return;
            }
            // 若不为空就正常超时死亡
            if (0 == tbOrder.getState()) {
                carOrderFeign.changeStateByUuid(4, correlationId);
                log.info("消息: id->" + correlationId + "内容->" + new String(message.getBody()) + "确实被超时消费了");
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
